package com.example.demo.nio;

import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.AsyncContext;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;


public class CustomCallable implements Callable{
    private static final Logger LOG = LoggerFactory.getLogger(CustomCallable.class);

    public AsyncContext asyncContext;
    private Callable<Object> task;
    private String uri;
    private  Map<String,String[]> params;

    public CustomCallable(AsyncContext asyncContext, Callable<Object> task){
        this.asyncContext= asyncContext;
        this.task= task;
        this.uri= (String) asyncContext.getRequest().getAttribute(Constant.URI);
        this.params= (Map<String, String[]>) asyncContext.getRequest().getAttribute(Constant.PARAMS);
    }
    @Override public Object call() throws Exception {
        Object o= task.call();
        if(o==null){
            callback(asyncContext,o);
        }else if(o instanceof String){
            callback(asyncContext, o);
        }else if(o instanceof CompletableFuture){
            CompletableFuture<Object> future= (CompletableFuture<Object>) o;
            future.thenAccept(o1 -> callback(asyncContext, o1))
                    .exceptionally(throwable -> {
                        callback(asyncContext,"");
                        return null;
                    });
        }else {
            callback(asyncContext, o);
        }
        return null;
    }

    private void callback(AsyncContext asyncContext,Object result){
        HttpServletResponse response= (HttpServletResponse) asyncContext.getResponse();
        try{
            if(result instanceof String){
                write(response, (String) result);
            }else {
                write(response, JSON.toJSONString(result));
            }
        }catch (Exception e){
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            e.printStackTrace();
            try {
                LOG.error("get info error for uri:{}, params:{}",uri,JSON.toJSONString(params),e);
            }catch (Exception e1){}
        }finally {
            asyncContext.complete();
        }
    }

    private void write(HttpServletResponse response,String result) throws IOException {
        response.getOutputStream().write(result.getBytes());
    }
}
